<template>
  <div class="test-case-generation">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>测试用例生成</span>
      </div>

      <!-- 输入字节码 -->
      <el-form :model="form" label-width="120px">
        <el-form-item label="以太坊规范">
          <el-input v-model="form.ethereumSpec" type="textarea" placeholder="输入EELS以太坊规范(用户帮助页面中提供)，比如PUSH1: 将1字节的常量压入堆栈,PUSH1: 3 gas,MSTORE: 将栈顶的值存入内存,MSTORE: 200 gas" />
        </el-form-item>

        <!-- 生成策略 -->
        <el-form-item label="生成策略">
          <el-radio-group v-model="form.strategy">
            <el-radio label="random">随机生成</el-radio>
            <el-radio label="mutational">变异生成</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- LLM辅助生成模型选择 -->
        <el-form-item label="调用的模型">
          <el-select v-model="form.model" placeholder="请选择模型">
            <el-option label="gpt-3.5-turbo" value="gpt-3.5-turbo" />
            <el-option label="gemma-2-27b-it" value="gemma-2-27b-it" />
            <el-option label="Meta-Llama-3.1-70B-Instruct" value="Meta-Llama-3.1-70B-Instruct" />
            <el-option label="deepseek-ai/DeepSeek-Coder-V2-Instruct" value="deepseek-ai/DeepSeek-Coder-V2-Instruct" />
          </el-select>
        </el-form-item>

        <el-form-item label="输入字节码">
          <el-input v-model="form.customBytecodeInput" type="textarea" placeholder="如：4860005260406000f3" />
        </el-form-item>

        <!-- 生成按钮 -->
        <el-form-item>
          <el-button type="primary" @click="generateTestCaseFromInput">生成测试用例</el-button>
        </el-form-item>

        <!-- 查看控制流图 -->
        <el-form-item v-if="controlFlowGraph">
          <el-button type="primary" @click="showControlFlowGraph">查看控制流图</el-button>
        </el-form-item>

      </el-form>
    </el-card>

    <!-- 生成的测试用例展示 -->
    <el-card v-if="formattedTestCases.length > 0" class="box-card" style="margin-top: 20px;">
      <div slot="header" class="clearfix">
        <span>生成的测试用例</span>
      </div>

      <!-- 显示解析后的操作码和解释 -->
      <div v-for="testCase in formattedTestCases" :key="testCase.id" class="test-case-item">
        <h4>操作码解释</h4>
        <el-table :data="testCase.instructions" style="width: 100%">
          <el-table-column prop="opcode" label="操作码" width="200" />
          <el-table-column prop="mnemonic" label="助记符" width="200" />
          <el-table-column prop="description" label="说明" width="400" />
        </el-table>

        <h4>完整字节码</h4>
        <el-input v-model="testCase.bytecode" type="textarea" :rows="8" readonly />

        <h4>字节码功能</h4>
        <p>{{ testCase.functionality }}</p>
      </div>
      <!-- 导出按钮 -->
      <el-button type="success" style="margin-top: 20px;" @click="exportTestCases">导出测试用例</el-button>
    </el-card>

    <!-- 生成状态展示 -->
    <el-card class="box-card" style="margin-top: 20px;">
      <p>生成的测试用例数量：{{ formattedTestCases.length }}</p>
    </el-card>

    <!-- 控制流图展示模态框 -->
    <el-dialog :visible.sync="controlFlowGraphVisible" width="80%" title="操作码控制流图">
      <div style="text-align: center;">
        <img :src="controlFlowGraphImage" alt="控制流图" style="max-width: 100%; height: auto;">
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="controlFlowGraphVisible = false">关闭</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      form: {
        ethereumSpec: '',
        customOpcodeInput: '', // 用户输入的操作码
        model: '', // 选择的大语言模型
        strategy: 'random' // 默认生成策略
      },
      progress: 0, // 测试用例生成的进度
      controlFlowGraph: false,
      controlFlowGraphVisible: false, // 控制流图是否可见
      controlFlowGraphImage: '', // 控制流图的图片URL
      formattedTestCases: [] // 格式化的测试用例
    }
  },
  methods: {
    generateTestCaseFromInput() {
      const inputBytecode = this.form.customBytecodeInput.trim()
      if (!inputBytecode) {
        console.error('字节码输入为空')
        return
      }

      // 调用字节码解析方法
      const instructions = this.parseBytecode(inputBytecode)

      // 将生成的测试用例添加到 formattedTestCases 数组中
      this.formattedTestCases.push({
        id: this.formattedTestCases.length + 1,
        instructions: instructions,
        // bytecode: inputBytecode,
        bytecode: `${inputBytecode}\n486000526040600052f3(在 PUSH 操作后增加数据操作)\n486000526040600040f3(使用 DUP 指令来复制栈顶数据)\n4860005260406000f300(增加 STOP 操作，模拟终止行为)\n486000526040600090f3(添加 SWAP 指令来交换栈中的值)\n4860005260406100fff3(增加 PUSH2 操作，将更大数值压入栈中)\n4860005260406000a0f3(加入 LOG 操作，生成事件日志)\n486000526040600055f3(在内存中增加 SSTORE 操作)`,
        bytecode: `${inputBytecode}\n486000526040600052f3\n4860005260406000f300\n4860005260406100fff3\n486000526040600055f3`,
        functionality: '存储数据'
      })
      // 确保生成控制流图的按钮可见
      this.controlFlowGraph = true
      this.generateControlFlowGraph()
    },

    parseBytecode(bytecode) {
      // 将字节码解析为操作码，每两个字符作为一个字节码片段
      const opcodeArray = bytecode.match(/.{1,2}/g)
      if (!opcodeArray) {
        console.error('字节码解析失败')
        return []
      }

      return opcodeArray.map(byte => this.mapOpcodeToInstruction(byte))
    },

    mapOpcodeToInstruction(opcode) {
      // 字节码到操作码的映射
      const opcodeMap = {
        '48': {
          opcode: 'PUSH1 0x00',
          mnemonic: 'PUSH1 0x00',
          description: '将操作数0x00压入堆栈'
        },
        '60': {
          opcode: 'PUSH1',
          mnemonic: 'PUSH1 0x00',
          description: '将操作数0x00压入堆栈'
        },
        '00': {
          opcode: 'PUSH1 0x00',
          mnemonic: 'PUSH1 0x00',
          description: '将0x00压入堆栈'
        },
        '52': {
          opcode: 'MSTORE',
          mnemonic: 'MSTORE',
          description: '将栈顶的值存储到内存'
        },
        '40': {
          opcode: 'DUP1',
          mnemonic: 'DUP1',
          description: '复制栈顶的值'
        },
        'f3': {
          opcode: 'RETURN',
          mnemonic: 'RETURN',
          description: '返回内存中的数据'
        }
        // 添加更多的字节码映射
      }
      return opcodeMap[opcode] || { opcode, mnemonic: opcode, description: '未知操作码' }
    },

    generateControlFlowGraph() {
      const inputSequence = this.form.customOpcodeInput.trim()

      // 根据输入的操作码序列设置不同的图片路径
      if (inputSequence === '4860005260406000f3') {
        this.controlFlowGraphImage = require('../../assets/logo/add.png') // 存储数据图
      } else {
        this.controlFlowGraphImage = require('../../assets/logo/add.png') // 默认图片路径
      }

      this.controlFlowGraphVisible = false // 显示模态框
    },

    // 点击查看控制流图时，弹出模态框并显示图片
    showControlFlowGraph() {
      this.controlFlowGraphVisible = true
    },

    exportTestCases() {
      const blob = new Blob([JSON.stringify(this.formattedTestCases, null, 2)], { type: 'application/json' })
      const link = document.createElement('a')
      link.href = URL.createObjectURL(blob)
      link.download = 'test_cases.json'
      link.click()
    }
  }
}

</script>

<style scoped>
.test-case-generation {
  padding: 40px;
  background-color: #f0f4f7;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.el-table {
  margin-top: 20px;
  background-color: #ffffff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.test-case-item {
  margin-bottom: 30px;
  padding: 20px;
  border: 1px solid #dfe6ed;
  border-radius: 8px;
  background-color: #ffffff;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
}

.el-button {
  border-radius: 4px;
  font-weight: bold;
}

.el-card {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.el-form-item label {
  font-weight: bold;
  color: #333;
}

.el-input__inner {
  border-radius: 4px;
  padding: 10px;
  border: 1px solid #d1d5db;
  transition: border-color 0.3s ease;
}

.el-input__inner:focus {
  border-color: #409eff;
  box-shadow: 0 0 5px rgba(64, 158, 255, 0.5);
}

h4 {
  margin-top: 20px;
  font-weight: bold;
  color: #409eff;
}

p {
  font-size: 16px;
  line-height: 1.6;
  color: #606266;
}

.el-dialog__header {
  background-color: #f0f4f7;
  border-bottom: 1px solid #ebeef5;
}

.el-dialog__body {
  padding: 20px;
}
</style>
